Amazon API Gatewayをブラウザから呼んでみた
はじめに
好物はインフラとフロントエンドのかじわらゆたかです。
Amazon API Gatewayのノウハウがいろいろ出ているので、 ブラウザから動かして見ようと思います。
流れとしてはAWS Lambdaで、S3 Pre-Signed URLの生成を実装し、 それをAmazon API Gatewayにデプロイします。
その後、ブラウザからデプロイされたAPIを実行し、 生成されたS3 Pre-Signed URLからアップロードされた画像を取得するといった形になります。
Pre-Signed URLの生成
AWS SDKを用いて、Presigned-URLを発行します。 AWS Gateway自体はTokyoリージョンには来ていませんが、 取得するS3のオブジェクトはTokyoリージョンから取得するといったケースで実装してみます。
app.js
'use strict'; var AWS = require('aws-sdk'); var bucket = 'cm-kajiwara-image'; var region = 'ap-northeast-1'; var s3 = new AWS.S3({ 'region': region }); var key = 'classmethod-icatch.png'; var params = { Bucket: bucket, Key: key, Expires: 60 }; exports.handler = function(event, context) { s3.getSignedUrl('getObject', params, function(err, url) { if(!err){ context.done(null,url); } }); };
以前紹介したAWS Lambda Functionをローカルで動かすdriver.jsを用い、 問題なく動くことを確認します。
$ node ./driver.js https://cm-kajiwara-image.s3-ap-northeast-1.amazonaws.com/classmethod-icatch.png AWS Access Key)&Expires=1436681110&Signature=(generated Signature)
今回Lambdaパッケージを作成するに辺り、 以下のページのサンプルプロジェクトを使いました。 AWS Lambdaの関数をnpmでパッケージ管理 - Qiita
このプロジェクトを用いることで、npmからAWS Lambda用のパッケージを作成・デプロイまで行うことが可能です。 上記のパッケージを使う際にハマった点を共有しておきます。
Scriptで定義されているコマンド郡の動かし方がわからない。
npm testだけは動いたのですが、他のbuild等のコマンドがうまく動きませんでした。 以下のようにすることでScript内で定義されているコマンドを動かすことが可能でした。
$npm run build
Roleの指定方法がわからない。
AWS Lambda Functionをアップロードする際に、 設定ファイルとして作成するlambdaConfig.jsonの内のRoleの記述方法わからず悩みました。 こちらはAWS Management Console内のIAM > Roles 内のarn:aws:iam::から始まる文字列を入力する必要があります。
npm run publishがうまくできない
package.jsonで指定しているaws-sdkのバージョンを更新した際に発生しました。 Lambdaのオブジェクトを作成する際に、apiVersionを明記すること必要がありました。
./script/publish.js
var lambda = new aws.Lambda({apiVersion:'2014-11-11', region: lambdaConfig.region}), zipPath = 'pkg/' + pkgConfig.name + '.zip';
publishしたfunctionのテストに失敗する。
npm run initLambdaで作成したひな形ファイルにはhandlerFile・handlerMethod が作成されていないのが原因です。 上記の作成と、未設定時にapp.jsに定義したhandlerでアップロードするようにしてみました。
./script/initLambda.js
var fs = require('fs'); var config = { region: '', description: '', role: '', memorySize: '128', timeout: '3', handlerFile:'', handlerMethod:'' }; fs.writeFileSync('./lambdaConfig.json',JSON.stringify(config));
./script/publish.js
function buildHnadlerName(lambdaConfig){ if(!lambdaConfig.handlerFile){ lambdaConfig.handlerFile = 'app'; } if(!lambdaConfig.handlerMethod){ lambdaConfig.handlerMethod = 'handler' } return lambdaConfig.handlerFile + '.' + lambdaConfig.handlerMethod; }
なお、上記の修正を適用した版を以下のブランチに配置しました。 こちらも併せて見ていただければ幸いです。 CM-Kajiwara/myFirstLambda
Amazon API Gatewayに作ったAWS Lambda Functionをデプロイする。
Deployに関しては、下記のブログを参照していただければと思います。 また、今回の作例ではAPI認証も実施しています。 Amazon API Gateway – API作成から動作確認までやってみる | Developers.IO Amazon API GatewayでAPIキー認証を設定する | Developers.IO
ブラウザからAmazon API Gatewayを呼ぶ
今回の作例では、Amazon API GatewayとWebサーバーとクロスドメインになるため、 ブラウザからCORSの設定を行う必要があります。 Amazon API Gateway をクロスオリジンで呼び出す (CORS) | Developers.IO
CORSの設定まで行えれば、呼び出すのはjQueryからでも、 生成されたSDKからでも呼び出すことが可能です。
<!doctype html> <button id="callSDKFunction">Sample Click callSDKFunction</button> <button id="calljQueryAjax">Sample Click calljQueryAjax</button> <div id="imageContainer"></div>
上記を動かした画像が下記になります。 ボタンを押下することで、Amazon API GatewayよりLambdaから S3のPre-Signed URLを取得し、imgタグに挿入しているといった流れになります。
まとめ
API Gatewayをブラウザから扱ってみました。 CORSの設定が必要ではありますが、 そこさえ押さえてしまえば普通のREST APIとして呼び出すことができました。